package foxesandrabbits.species;

import java.util.Iterator;
import java.util.List;
import foxesandrabbits.field.Field;
import foxesandrabbits.field.Location;

/**
 * A class representing shared characteristics of killers species.
 * 
 * @author Baptiste Viale and Hadrien Luttiau
 */

public abstract class Killer extends AliveObject{

	protected int foodLevel;
	protected int FOOD_VALUE;
	@SuppressWarnings("rawtypes")
	protected Class[] preys;

	public Killer(boolean randomAge, Field field, Location location, int foodValue, double breedingP) {
		super(randomAge, field, location, breedingP);
		FOOD_VALUE = foodValue;
		if(!randomAge) 
			foodLevel = FOOD_VALUE;
		else 
			foodLevel = rand.nextInt(FOOD_VALUE);
		preys = new Class[]{};
	}

	public int getFoodLevel() {
		return foodLevel;
	}

	public void setFoodLevel(int foodLevel) {
		this.foodLevel = foodLevel;
	}

	/**
	 * Make this fox more hungry. This could result in the fox's death.
	 */
	protected void incrementHunger()
	{
		foodLevel--;
		if(foodLevel <= 0) {
			setDead();
			//System.out.println("A "+this.getClass().getName() + " dies of starvation !");
		}
	}

	/**
	 * Look for rabbits adjacent to the current location.
	 * Only the first live rabbit is eaten.
	 * @return Where food was found, or null if it wasn't.
	 */
	protected Location findFood()
	{
		Field field = getField();
		List<Location> adjacent = field.adjacentLocations(getLocation());
		Iterator<Location> it = adjacent.iterator();
		while(it.hasNext()) {
			Location where = it.next();
			Object animal = field.getObjectAt(where);

			for (Class<?> classPrey : this.preys)
			{
				if(animal != null && animal.getClass().equals(classPrey)) {
					AliveObject prey = (AliveObject) animal;

					if(prey.isAlive() && animal instanceof Rabbit && rand.nextInt(2)==1 ) 
					{ 
						prey.setDead();
						foodLevel = FOOD_VALUE;
						//System.out.println("A " + prey.getClass().getName() + " has been killed by a " + this.getClass().getName());
						return where;
					}
					if(prey.isAlive() && !(animal instanceof Rabbit)) 
					{ 
						prey.setDead();
						foodLevel = FOOD_VALUE;
						//System.out.println("A " + prey.getClass().getName() + " has been killed by a " + this.getClass().getName());
						return where;
					}
				}
			}
		}
		return null;
	}
	
	/**
	 * This is what the fox does most of the time: it hunts for
	 * rabbits. In the process, it might breed, die of hunger,
	 * or die of old age.
	 * @param newAnimals A list to return newly born animals.
	 */
	public void act(List<AliveObject> newAnimals)
	{
		if(this.getClass()!=Hunter.class)
			super.act(newAnimals);
		incrementHunger();
		if(isAlive()) {
			Location newLocation = findFood();
			if(newLocation == null) { 
				// No food found - try to move to a free location.
				newLocation = getField().freeAdjacentLocation(getLocation());
			}
			// See if it was possible to move.
			if(newLocation != null) {
				setLocation(newLocation);
			}
			else {
				// Overcrowding.
				setDead();
			}
		}
	}
}
